#ifndef OHOS_RIVE_RESOURCE_H
#define OHOS_RIVE_RESOURCE_H

#include "napi/native_api.h"
#include <arkui/native_node_napi.h>
#include <functional>
#include <vector>

namespace ohos_rive {
template <typename T>
class NativeResource {
private:
    T resource;
    napi_env env;

public:
    NativeResource(const NativeResource &) = delete;
    NativeResource &operator=(const NativeResource &) = delete;

    NativeResource(T res, napi_env env) : resource(res), env(env) {}

    NativeResource(NativeResource &&other) noexcept : resource(other.resource), env(other.env)
    {
        other.resource = nullptr;
        other.env = nullptr;
    }

    ~NativeResource() noexcept
    {
        if (resource != nullptr) {
            // 只有当 T 是 napi_ref 类型时才调用 napi_delete_reference
            if constexpr (std::is_same_v<T, napi_ref>) {
                napi_delete_reference(env, resource);
            }
            // 对于 napi_value 不需要特殊处理，N-API 会自动管理
            resource = nullptr;
        }
    }

    NativeResource &operator=(NativeResource &&other) noexcept
    {
        if (this != &other) {
            if (resource && env) {
                if (std::is_same<T, napi_ref>::value) {
                    napi_delete_reference(env, resource);
                }
            }
            resource = other.resource;
            env = other.env;
            other.resource = nullptr;
            other.env = nullptr;
        }
        return *this;
    }

    explicit operator T() const
    {
        return resource;
    }

    T get() const
    {
        return resource;
    }

    T release() noexcept
    {
        T toRelease = resource;
        resource = nullptr;
        return toRelease;
    }
};

template <typename T>
NativeResource<T> MakeNativeResource(T res, napi_env env)
{
    return NativeResource<T>(res, env);
}

void RegisterClass(napi_env env, napi_value args[], size_t argc);
void UnregisterClass(napi_env env, napi_value args[], size_t argc);

std::string GetClassName(napi_env env, napi_value cls);

NativeResource<napi_value> FindClass(napi_env env, const char *name);

NativeResource<napi_value> GetObjectClass(napi_env env, napi_value obj);

NativeResource<napi_value> GetStaticObjectField(napi_env env, napi_value clazz, const char *fieldName);

NativeResource<napi_value> GetObjectFromMethod(napi_env env, napi_value obj, const char *methodName, ...);

NativeResource<napi_value> GetObjectArrayElement(napi_env env, napi_value jarray, size_t index);

NativeResource<napi_value> MakeObject(napi_env env, napi_value method, int argsCount, napi_value *args);

NativeResource<napi_value> MakeNapiString(napi_env env, const char *str);
NativeResource<napi_value> MakeNapiString(napi_env env, const std::string &str);

std::vector<uint8_t> ByteArrayToUint8Vec(napi_env env, napi_value byteArray);
NativeResource<napi_value> VecStringToNapiStringList(napi_env env, const std::vector<std::string> &strs);

} // namespace ohos_rive

#endif // OHOS_RIVE_RESOURCE_H
